Visaptverošs ceļvedis globālajiem izstrādātājiem par sinhronizācijas kontroli. Iepazīstiet bloķēšanas sinhronizāciju, muteksi, semaforus, strupceļus un paraugprakses.
Konkurētspējas apgūšana: padziļināta bloķēšanas sinhronizācijas analīze
Iedomājieties rosīgu profesionālu virtuvi. Vairāki pavāri strādā vienlaicīgi, un visiem ir nepieciešama piekļuve kopīgai sastāvdaļu noliktavai. Ja divi pavāri vienlaikus mēģinātu paķert pēdējo retu garšvielu burciņu, kurš to dabūs? Ko darīt, ja viens pavārs atjaunina receptes kartīti, kamēr otrs to lasa, kā rezultātā rodas nepilnīga, bezjēdzīga instrukcija? Šī virtuves haosa aina ir lieliska analoģija modernās programmatūras izstrādes galvenajam izaicinājumam: konkurētspējai.
Mūsdienu daudzkodolu procesoru, sadalīto sistēmu un ļoti atsaucīgu lietojumprogrammu pasaulē konkurētspēja – dažādu programmas daļu spēja izpildīties nepareizā secībā vai daļējā secībā, neietekmējot galīgo rezultātu – nav greznība; tā ir nepieciešamība. Tā ir ātro tīmekļa serveru, vienmērīgu lietotāja interfeisu un jaudīgu datu apstrādes cauruļvadu dzinējspēks. Tomēr šī jauda rada ievērojamu sarežģītību. Kad vairāki pavedieni vai procesi vienlaicīgi piekļūst kopīgiem resursiem, tie var traucēt viens otram, izraisot bojātus datus, neparedzamu darbību un kritiskas sistēmas kļūmes. Šeit palīgā nāk konkurētspējas kontrole.
Šis visaptverošais ceļvedis izskaidros visvienkāršāko un visplašāk izmantoto paņēmienu šī kontrolētā haosa pārvaldīšanai: bloķēšanas sinhronizāciju. Mēs izskaidrosim, kas ir bloķēšanas elementi, izpētīsim to dažādās formas, izanalizēsim to bīstamās nepilnības un izveidosim globālu paraugprakses kopumu, lai rakstītu izturīgu, drošu un efektīvu konkurētspējīgu kodu.
Kas ir konkurētspējas kontrole?
Pēc būtības konkurētspējas kontrole ir datorzinātņu disciplīna, kas veltīta vienlaicīgu darbību pārvaldībai ar kopīgiem datiem. Tās galvenais mērķis ir nodrošināt, lai vienlaicīgas darbības izpildītos pareizi, netraucējot viena otru, saglabājot datu integritāti un konsekvenci. Domājiet par to kā par virtuves vadītāju, kurš nosaka noteikumus, kā pavāri var piekļūt noliktavai, lai novērstu izšļakstīšanos, sajaukšanos un sastāvdaļu izšķērdēšanu.
Datu bāzu pasaulē konkurētspējas kontrole ir būtiska, lai saglabātu ACID īpašības (Atomiskums, Konsekvence, Izolācija, Noturība), īpaši Izolācija. Izolācija nodrošina, ka transakciju vienlaicīga izpilde rada sistēmas stāvokli, kas tiktu iegūts, ja transakcijas tiktu izpildītas seriāli, viena pēc otras.
Pastāv divas galvenās pieejas konkurētspējas kontroles ieviešanai:
- Optimistiskā konkurētspējas kontrole: Šī pieeja pieņem, ka konflikti ir reti. Tā ļauj operācijām notikt bez iepriekšējiem pārbaudījumiem. Pirms izmaiņu apstiprināšanas sistēma pārbauda, vai cita operācija ir mainījusi datus starplaikā. Ja tiek konstatēts konflikts, operācija parasti tiek atsaukta un atkārtota. Tā ir stratēģija “lūgt piedošanu, nevis atļauju”.
- Pesimistiskā konkurētspējas kontrole: Šī pieeja pieņem, ka konflikti ir iespējami. Tā liek operācijai iegūt resursa bloķēšanu pirms piekļuves tam, tādējādi novēršot citu operāciju traucējumus. Tā ir stratēģija “lūgt atļauju, nevis piedošanu”.
Šis raksts koncentrējas tikai uz pesimistisko pieeju, kas ir bloķēšanas sinhronizācijas pamats.
Galvenā problēma: sacīkšu nosacījumi
Pirms mēs varam novērtēt risinājumu, mums ir pilnībā jāsaprot problēma. Visizplatītākā un viltīgākā kļūda konkurētspējīgā programmēšanā ir sacīkšu nosacījums. Sacīkšu nosacījums rodas, kad sistēmas darbība ir atkarīga no nekontrolējamu notikumu, piemēram, operētājsistēmas pavedienu plānošanas, neprognozējamās secības vai laika.
Apskatīsim klasisko piemēru: kopīgs bankas konts. Pieņemsim, ka kontā ir 1000 $ atlikums, un divi vienlaicīgi pavedieni mēģina iemaksāt katrs 100 $.
Šeit ir vienkāršota iemaksas operāciju secība:
- Nolasīt pašreizējo atlikumu no atmiņas.
- Pievienot iemaksas summu šai vērtībai.
- Rakstīt jauno vērtību atpakaļ atmiņā.
Pareiza, seriāla izpilde rezultētu ar galīgo atlikumu 1200 $. Bet kas notiek konkurētspējīgā scenārijā?
Iespējamā operāciju savstarpēja ietekmēšanās:
- 1. pavediens: nolasa atlikumu (1000 $).
- Konteksta pārslēgšana: Operētājsistēma aptur 1. pavedienu un palaida 2. pavedienu.
- 2. pavediens: nolasa atlikumu (joprojām 1000 $).
- 2. pavediens: aprēķina savu jauno atlikumu (1000 $ + 100 $ = 1100 $).
- 2. pavediens: raksta jauno atlikumu (1100 $) atpakaļ atmiņā.
- Konteksta pārslēgšana: Operētājsistēma atsāk 1. pavedienu.
- 1. pavediens: aprēķina savu jauno atlikumu, pamatojoties uz iepriekš nolasīto vērtību (1000 $ + 100 $ = 1100 $).
- 1. pavediens: raksta jauno atlikumu (1100 $) atpakaļ atmiņā.
Galīgais atlikums ir 1100 $, nevis paredzētie 1200 $. 100 $ iemaksa ir izzudusi gaisā sacīkšu nosacījuma dēļ. Koda bloks, kurā tiek piekļūts kopīgajam resursam (kontu atlikumam), ir pazīstams kā kritiskā sadaļa. Lai novērstu sacīkšu nosacījumus, mums jānodrošina, ka tikai viens pavediens var izpildīties kritiskajā sadaļā jebkurā dotajā laikā. Šis princips tiek saukts par savstarpēju izslēgšanu.
Ievads bloķēšanas sinhronizācijā
Bloķēšanas sinhronizācija ir galvenais savstarpējas izslēgšanas nodrošināšanas mehānisms. Bloķēšanas elements (pazīstams arī kā muteks) ir sinhronizācijas primitīvs, kas darbojas kā kritiskās sadaļas aizsargs.
Vienas lietotāja vannas istabas atslēgas analoģija ir ļoti piemērota. Vannas istaba ir kritiskā sadaļa, un atslēga ir bloķēšanas elements. Daudzi cilvēki (pavedieni) var stāvēt ārā rindā, bet tikai tas, kuram ir atslēga, var ieiet. Kad viņi ir pabeiguši, viņi iziet un atgriež atslēgu, ļaujot nākamajam rindā to paņemt un ieiet.
Bloķēšanas elementi atbalsta divas pamatoperācijas:
- Iegūt (vai bloķēt): Pavediens izsauc šo operāciju pirms kritiskās sadaļas ieiešanas. Ja bloķēšanas elements ir pieejams, pavediens to iegūst un turpina. Ja bloķēšanas elements jau ir cita pavediena turēts, zvanošais pavediens bloķēsies (vai “aizmigs”), līdz bloķēšanas elements tiks atbrīvots.
- Atbrīvot (vai atbloķēt): Pavediens izsauc šo operāciju pēc tam, kad tas ir pabeidzis kritiskās sadaļas izpildi. Tas padara bloķēšanas elementu pieejamu citiem gaidošajiem pavedieniem, lai tos iegūtu.
Ietīstot mūsu bankas konta loģiku ar bloķēšanas elementu, mēs varam garantēt tās pareizību:
iegūt_bloķēšanu(konts_bloķēšana);
// --- Kritiskās sadaļas sākums ---
balansa_vērtība = nolasīt_atlikumu();
jaunais_balansa_stāvoklis = balansa_vērtība + summa;
rakstīt_atlikumu(jaunais_balansa_stāvoklis);
// --- Kritiskās sadaļas beigas ---
atlaist_bloķēšanu(konts_bloķēšana);
Tagad, ja 1. pavediens vispirms iegūst bloķēšanu, 2. pavediens būs spiests gaidīt, līdz 1. pavediens pabeigs visus trīs soļus un atbrīvos bloķēšanu. Operācijas vairs netiks savstarpēji ietekmētas, un sacīkšu nosacījums tiks novērsts.
Bloķēšanas elementi veidi: programmētāja rīku komplekts
Lai gan bloķēšanas elementu pamatkoncepcija ir vienkārša, dažādi scenāriji prasa dažādus bloķēšanas mehānismu veidus. Pieejamo bloķēšanas elementu rīku komplekta izpratne ir būtiska efektīvu un pareizu konkurētspējīgu sistēmu veidošanai.
Muteksu (savstarpējas izslēgšanas) bloķēšanas elementi
Mutekss ir vienkāršākais un visizplatītākais bloķēšanas elementu veids. Tas ir binārs bloķēšanas elements, kas nozīmē, ka tam ir tikai divi stāvokļi: bloķēts vai atbloķēts. Tas ir paredzēts, lai nodrošinātu stingru savstarpēju izslēgšanu, nodrošinot, ka tikai viens pavediens jebkurā laikā var būt bloķēšanas elementa īpašnieks.
- Īpašnieks: lielākajai daļai muteksu implementāciju galvenā iezīme ir īpašnieks. Pavediens, kas iegūst muteksu, ir vienīgais pavediens, kam ir atļauts to atbrīvot. Tas novērš vienu pavedienu no nejaušas (vai ļaunprātīgas) citas pavediena lietotās kritiskās sadaļas atbloķēšanas.
- Lietošanas gadījums: Muteksi ir noklusējuma izvēle īsu, vienkāršu kritisko sadaļu aizsardzībai, piemēram, kopīgās mainīgās atjaunināšanai vai datu struktūras modificēšanai.
Semafori
Semafors ir vispārīgāks sinhronizācijas primitīvs, ko izgudrojis nīderlandiešu datorspeciālists Edsgers V. Dijkštra. Atšķirībā no muteksa, semafors uztur nenegatīva vesela skaitļa vērtības skaitītāju.
Tas atbalsta divas atomiskas operācijas:
- gaidīt() (vai P operācija): Samazina semafora skaitītāju. Ja skaitītājs kļūst negatīvs, pavediens bloķējas, līdz skaitītājs ir lielāks vai vienāds ar nulli.
- signāls() (vai V operācija): Palielina semafora skaitītāju. Ja uz semafora ir bloķēti kādi pavedieni, viens no tiem tiek atbloķēts.
Pastāv divi galvenie semaforu veidi:
- Binārs semafors: Skaitītājs ir inicializēts uz 1. Tas var būt tikai 0 vai 1, padarot to funkcionāli līdzvērtīgu muteksam.
- Skaitīšanas semafors: Skaitītāju var inicializēt jebkuram veselam skaitlim N > 1. Tas ļauj vienlaicīgi piekļūt resursam līdz pat N pavedieniem. To izmanto, lai kontrolētu piekļuvi ierobežotam resursu kopumam.
Piemērs: Iedomājieties tīmekļa lietojumprogrammu ar savienojumu kopumu, kas var apstrādāt ne vairāk kā 10 vienlaicīgus datu bāzes savienojumus. Skaitīšanas semafors, kas inicializēts uz 10, var lieliski to pārvaldīt. Katram pavedienam ir jāveic `gaidīt()` uz semaforu pirms savienojuma paņemšanas. 11. pavediens bloķēsies, līdz viens no pirmajiem 10 pavedieniem pabeigs savu datu bāzes darbu un veiks `signāls()` uz semafora, atgriežot savienojumu kopumā.
Lasīšanas-rakstīšanas bloķēšanas elementi (kopīgie/ekskluzīvie bloķēšanas elementi)
Izplatīts modelis konkurētspējīgās sistēmās ir tāds, ka dati tiek lasīti daudz biežāk nekā tiek rakstīti. Izmantojot vienkāršu muteksu šajā scenārijā, ir neefektīvi, jo tas neļauj vairākiem pavedieniem vienlaicīgi lasīt datus, lai gan lasīšana ir droša, nemodificējoša operācija.
Lasīšanas-rakstīšanas bloķēšanas elements risina šo problēmu, nodrošinot divus bloķēšanas režīmus:
- Kopīgs (lasīšanas) bloķēšanas elements: Vairāki pavedieni var vienlaicīgi iegūt lasīšanas bloķēšanas elementu, kamēr neviens pavediens netur rakstīšanas bloķēšanas elementu. Tas nodrošina augstu konkurētspējīgu lasīšanu.
- Ekskluzīvs (rakstīšanas) bloķēšanas elements: Tikai viens pavediens var vienlaicīgi iegūt rakstīšanas bloķēšanas elementu. Kad pavediens tur rakstīšanas bloķēšanas elementu, visi citi pavedieni (gan lasītāji, gan rakstītāji) tiek bloķēti.
Analógija ir dokuments kopīgajā bibliotēkā. Daudzi cilvēki var vienlaicīgi lasīt dokumenta kopijas (kopīgs lasīšanas bloķēšanas elements). Tomēr, ja kāds vēlas rediģēt dokumentu, viņam tas ir jāizņem ekskluzīvi, un neviens cits nevar to lasīt vai rediģēt, kamēr viņš nav pabeidzis (ekskluzīvs rakstīšanas bloķēšanas elements).
Rekursīvie bloķēšanas elementi (atgriežamie bloķēšanas elementi)
Kas notiek, ja pavediens, kuram jau pieder mutekss, mēģina to iegūt vēlreiz? Ar standarta muteksu tas izraisītu tūlītēju strupceļu — pavediens mūžīgi gaidīs, kamēr pats atbrīvos bloķēšanas elementu. Rekursīvais bloķēšanas elements (vai atgriežamais bloķēšanas elements) ir paredzēts šīs problēmas risināšanai.
Rekursīvais bloķēšanas elements ļauj tam pašam pavedienam iegūt to pašu bloķēšanas elementu vairākas reizes. Tas uztur iekšēju īpašnieka skaitītāju. Bloķēšanas elements tiek pilnībā atbrīvots tikai tad, kad īpašnieka pavediens ir izsaucis `atbrīvot()` tikpat reižu, cik izsaucis `iegūt()` . Tas ir īpaši noderīgi rekursīvās funkcijās, kurām nepieciešams aizsargāt kopīgu resursu izpildes laikā.
Bloķēšanas elementu briesmas: izplatītas nepilnības
Lai gan bloķēšanas elementi ir jaudīgi, tie ir abpusgriezīgs zobens. Nepareiza bloķēšanas elementu izmantošana var radīt kļūdas, ko ir daudz grūtāk diagnosticēt un labot nekā vienkāršus sacīkšu nosacījumus. Tie ietver strupceļus, livelockus un veiktspējas pudeļus.
Strupceļš
Strupceļš ir visbaisākais scenārijs konkurētspējīgā programmēšanā. Tas rodas, kad divi vai vairāki pavedieni ir neierobežoti bloķēti, katrs gaidot resursu, ko tur cits pavediens tajā pašā kopā.
Apsveriet vienkāršu scenāriju ar diviem pavedieniem (1. pavediens, 2. pavediens) un diviem bloķēšanas elementiem (Bloķēšanas A, Bloķēšanas B):
- 1. pavediens iegūst Bloķēšanas A.
- 2. pavediens iegūst Bloķēšanas B.
- Tagad 1. pavediens mēģina iegūt Bloķēšanas B, bet to tur 2. pavediens, tāpēc 1. pavediens bloķējas.
- Tagad 2. pavediens mēģina iegūt Bloķēšanas A, bet to tur 1. pavediens, tāpēc 2. pavediens bloķējas.
Abi pavedieni tagad ir pastāvīgā gaidīšanas stāvoklī. Lietojumprogramma apstājas. Šī situācija rodas četru nepieciešamo nosacījumu (Coffman nosacījumu) dēļ:
- Savstarpēja izslēgšana: Resursi (bloķēšanas elementi) nevar tikt kopīgoti.
- Turēšana un gaidīšana: Pavediens tur vismaz vienu resursu, kamēr gaida citu.
- Nav atsavināšanas: Resursu nevar piespiedu kārtā atņemt pavedienam, kas to tur.
- Cirkulārā gaidīšana: Pastāv divu vai vairāku pavedienu ķēde, kur katrs pavediens gaida resursu, ko tur nākamais pavediens ķēdē.
Strupceļa novēršana ietver vismaz viena no šiem nosacījumiem pārkāpšanu. Visizplatītākā stratēģija ir pārkāpt cirkulārās gaidīšanas nosacījumu, nodrošinot stingru globālu bloķēšanas elementu iegūšanas kārtību.
Livelock
Livelock ir smalkāks strupceļa brālēns. Livelock gadījumā pavedieni netiek bloķēti — tie aktīvi darbojas —, bet tie neveic nekādu progresu. Viņi ir iestrēguši ciklā, reaģējot uz otra stāvokļa izmaiņām, neveicot nekādu noderīgu darbu.
Klasiskā analoģija ir divi cilvēki, kas mēģina viens otram paiet garām šaurā koridorā. Viņi abi mēģina būt laipni un pakāpties pa kreisi, bet rezultātā viens otru bloķē. Pēc tam viņi abi pakāpjas pa labi, atkal viens otru bloķējot. Viņi aktīvi kustas, bet nekustas pa koridoru. Programmatūrā tas var notikt ar slikti izstrādātiem strupceļu atkopšanas mehānismiem, kur pavedieni atkārtoti atkāpjas un mēģina vēlreiz, tikai lai atkal saskartos.
Badā nīkšana
Badā nīkšana rodas, kad pavedienam tiek pastāvīgi liegta piekļuve nepieciešamam resursam, pat ja resurss kļūst pieejams. Tas var notikt sistēmās ar plānošanas algoritmiem, kas nav “godīgi”. Piemēram, ja bloķēšanas mehānisms vienmēr piešķir piekļuvi augstas prioritātes pavedieniem, zemas prioritātes pavediens, iespējams, nekad nedabūs iespēju darboties, ja pastāvīgi ir augstas prioritātes pretendentu plūsma.
Veiktspējas pārslodze
Bloķēšanas elementi nav bez maksas. Tie rada veiktspējas pārslodzi vairākos veidos:
- Iegūšanas/atbrīvošanas izmaksas: Bloķēšanas elementa iegūšana un atbrīvošana ietver atomiskas operācijas un atmiņas žogus, kas ir aprēķināšanas ziņā dārgāki nekā parastas instrukcijas.
- Konflikts: Kad vairāki pavedieni bieži konkurē par vienu un to pašu bloķēšanas elementu, sistēma pavada ievērojamu laiku, pārslēdzot kontekstu un plānojot pavedienus, nevis veicot produktīvu darbu. Augsts konflikts efektīvi serializē izpildi, atceļot paralēlismu.
Paraugprakses bloķēšanas sinhronizācijai
Pareiza un efektīva konkurētspējīga koda rakstīšana ar bloķēšanas elementiem prasa disciplīnu un noteiktu paraugprakses ievērošanu. Šie principi ir universāli piemērojami neatkarīgi no programmēšanas valodas vai platformas.
1. Saglabājiet kritiskās sadaļas mazas
Bloķēšanas elements ir jāsaglabā pēc iespējas īsāku laiku. Jūsu kritiskā sadaļa ir jāsatur tikai ar kodu, kuram obligāti jābūt aizsargātam no vienlaicīgas piekļuves. Jebkuras nekritiskas operācijas (piemēram, I/O, sarežģīti aprēķini, kas nav saistīti ar kopīgo stāvokli) jāveic ārpus bloķētā apgabala. Jo ilgāk jūs turat bloķēšanas elementu, jo lielāka ir konflikta iespēja un jo vairāk jūs bloķējat citus pavedienus.
2. Izvēlieties pareizo bloķēšanas elementa granularitāti
Bloķēšanas elementa granularitāte attiecas uz datiem, ko aizsargā viens bloķēšanas elements.
- Kopējā granularitātes bloķēšana: Vienu bloķēšanas elementu izmantošana, lai aizsargātu lielu datu struktūru vai visu apakšsistēmu. Tas ir vienkāršāk ieviest un izprast, bet var radīt augstu konfliktu, jo nesaistītas operācijas ar dažādām datu daļām visas tiek serializētas ar to pašu bloķēšanas elementu.
- Smalkas granularitātes bloķēšana: Vairāku bloķēšanas elementu izmantošana, lai aizsargātu dažādas, neatkarīgas datu struktūras daļas. Piemēram, nevis viens bloķēšanas elements visai atmiņas tabulai, bet katram spainim var būt atsevišķs bloķēšanas elements. Tas ir sarežģītāk, bet var ievērojami uzlabot veiktspēju, ļaujot vairāk reālas paralēluma.
Izvēle starp tiem ir kompromiss starp vienkāršību un veiktspēju. Sāciet ar kopīgākiem bloķēšanas elementiem un tikai tad pārejiet uz smalkākas granularitātes bloķēšanas elementiem, ja veiktspējas profilēšana parāda, ka bloķēšanas elementa konflikts ir pudeļu kakls.
3. Vienmēr atbrīvojiet savus bloķēšanas elementus
Bloķēšanas elementa neatbrīvošana ir katastrofāla kļūda, kas, visticamāk, apturēs jūsu sistēmu. Izplatīts šīs kļūdas avots ir tad, kad kritiskās sadaļas laikā notiek izņēmums vai agrīna atgriešanās. Lai to novērstu, vienmēr izmantojiet valodu konstrukcijas, kas garantē tīrīšanu, piemēram, try...finally blokus Java vai C#, vai RAII (resursu iegūšana ir inicializācija) modeļus ar tvēruma bloķēšanas elementiem C++.
Piemērs (pseudokods, izmantojot try-finally):
mans_bloķēšanas_elements.iegūt();
try {
// Kritiskās sadaļas kods, kas var izraisīt izņēmumu
} finally {
mans_bloķēšanas_elements.atbrīvot(); // Tas tiek garantēti izpildīts
}
4. Ievērojiet stingru bloķēšanas elementu kārtību
Lai novērstu strupceļus, efektīvākā stratēģija ir pārkāpt cirkulārās gaidīšanas nosacījumu. Izveidojiet stingru, globālu un patvaļīgu kārtību vairāku bloķēšanas elementu iegūšanai. Ja kādam pavedienam kādreiz ir jātur gan Bloķēšanas A, gan Bloķēšanas B, tam vienmēr jāiegūst Bloķēšanas A pirms Bloķēšanas B iegūšanas. Šis vienkāršais noteikums padara cirkulāro gaidīšanu neiespējamu.
5. Apsveriet bloķēšanas elementu alternatīvas
Lai gan tie ir pamati, bloķēšanas elementi nav vienīgais konkurētspējas kontroles risinājums. Augstas veiktspējas sistēmām ir vērts izpētīt uzlabotus paņēmienus:
- Bezbloķēšanas datu struktūras: Tās ir sarežģītas datu struktūras, kas izstrādātas, izmantojot zema līmeņa atomiskas aparatūras instrukcijas (piemēram, Compare-And-Swap), kas ļauj vienlaicīgi piekļūt bez bloķēšanas elementu izmantošanas. Tās ir ļoti grūti pareizi ieviest, bet var piedāvāt izcilu veiktspēju augsta konflikta gadījumā.
- Nemainīgi dati: Ja dati nekad netiek modificēti pēc to izveidošanas, tos var brīvi kopīgot starp pavedieniem bez nepieciešamības pēc sinhronizācijas. Tas ir funkcionālās programmēšanas pamatprincips un arvien populārāks veids, kā vienkāršot konkurētspējīgus dizainus.
- Programmatūras transakciju atmiņa (STM): Augstāka līmeņa abstrakcija, kas ļauj izstrādātājiem definēt atomiskas transakcijas atmiņā, līdzīgi kā datu bāzē. STM sistēma aiz ainas apstrādā sarežģītās sinhronizācijas detaļas.
Secinājums
Bloķēšanas sinhronizācija ir konkurētspējīgas programmēšanas stūrakmens. Tā nodrošina jaudīgu un tiešu veidu, kā aizsargāt kopīgos resursus un novērst datu bojājumus. No vienkārša muteksa līdz niansētākam lasīšanas-rakstīšanas bloķēšanas elementam, šie primitīvi ir būtiskas ierīces jebkuram izstrādātājam, kas veido daudzvītņotu lietojumprogrammu.
Tomēr šī jauda prasa atbildību. Prasme dziļi izprast potenciālās nepilnības — strupceļus, livelockus un veiktspējas pasliktināšanos — nav brīvprātīga. Ievērojot paraugprakses, piemēram, minimizējot kritiskās sadaļas izmēru, izvēloties piemērotu bloķēšanas elementa granularitāti un nodrošinot stingru bloķēšanas elementu kārtību, jūs varat izmantot konkurētspējas jaudu, vienlaikus izvairoties no tās briesmām.
Konkurētspējas apgūšana ir ceļojums. Tas prasa rūpīgu dizainu, stingru testēšanu un domāšanas veidu, kas vienmēr apzinās sarežģītās mijiedarbības, kas var notikt, kad pavedieni darbojas paralēli. Apgūstot bloķēšanas elementu mākslu, jūs veicat kritisku soli, lai izveidotu programmatūru, kas ir ne tikai ātra un atsaucīga, bet arī izturīga, uzticama un pareiza.